DESeq2 analysis of peak universe (joint peak set called in any
condition, must be called in all three replicates, MACS3)
bw_dir <- "/Volumes/DATA/DATA/Puck/bigwig/"
chromhmm <- "../genome/ESC_10_segments.mm39.bed"
library("wigglescout")
library("ggpubr")
Loading required package: ggplot2
library("ggplot2")
library("DESeq2")
Loading required package: S4Vectors
Warning: package ‘S4Vectors’ was built under R version 4.2.2Loading required package: stats4
Loading required package: BiocGenerics
Attaching package: ‘BiocGenerics’
The following objects are masked from ‘package:stats’:
IQR, mad, sd, var, xtabs
The following objects are masked from ‘package:base’:
anyDuplicated, aperm, append, as.data.frame, basename, cbind,
colnames, dirname, do.call, duplicated, eval, evalq, Filter,
Find, get, grep, grepl, intersect, is.unsorted, lapply, Map,
mapply, match, mget, order, paste, pmax, pmax.int, pmin,
pmin.int, Position, rank, rbind, Reduce, rownames, sapply,
setdiff, sort, table, tapply, union, unique, unsplit,
which.max, which.min
Attaching package: ‘S4Vectors’
The following objects are masked from ‘package:base’:
expand.grid, I, unname
Loading required package: IRanges
Loading required package: GenomicRanges
Warning: package ‘GenomicRanges’ was built under R version 4.2.2Loading required package: GenomeInfoDb
Warning: package ‘GenomeInfoDb’ was built under R version 4.2.2Loading required package: SummarizedExperiment
Loading required package: MatrixGenerics
Loading required package: matrixStats
Attaching package: ‘MatrixGenerics’
The following objects are masked from ‘package:matrixStats’:
colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse,
colCounts, colCummaxs, colCummins, colCumprods, colCumsums,
colDiffs, colIQRDiffs, colIQRs, colLogSumExps, colMadDiffs,
colMads, colMaxs, colMeans2, colMedians, colMins,
colOrderStats, colProds, colQuantiles, colRanges, colRanks,
colSdDiffs, colSds, colSums2, colTabulates, colVarDiffs,
colVars, colWeightedMads, colWeightedMeans, colWeightedMedians,
colWeightedSds, colWeightedVars, rowAlls, rowAnyNAs, rowAnys,
rowAvgsPerColSet, rowCollapse, rowCounts, rowCummaxs,
rowCummins, rowCumprods, rowCumsums, rowDiffs, rowIQRDiffs,
rowIQRs, rowLogSumExps, rowMadDiffs, rowMads, rowMaxs,
rowMeans2, rowMedians, rowMins, rowOrderStats, rowProds,
rowQuantiles, rowRanges, rowRanks, rowSdDiffs, rowSds,
rowSums2, rowTabulates, rowVarDiffs, rowVars, rowWeightedMads,
rowWeightedMeans, rowWeightedMedians, rowWeightedSds,
rowWeightedVars
Loading required package: Biobase
Welcome to Bioconductor
Vignettes contain introductory material; view with
'browseVignettes()'. To cite Bioconductor, see
'citation("Biobase")', and for packages 'citation("pkgname")'.
Attaching package: ‘Biobase’
The following object is masked from ‘package:MatrixGenerics’:
rowMedians
The following objects are masked from ‘package:matrixStats’:
anyMissing, rowMedians
library("dplyr")
Attaching package: ‘dplyr’
The following object is masked from ‘package:Biobase’:
combine
The following object is masked from ‘package:matrixStats’:
count
The following objects are masked from ‘package:GenomicRanges’:
intersect, setdiff, union
The following object is masked from ‘package:GenomeInfoDb’:
intersect
The following objects are masked from ‘package:IRanges’:
collapse, desc, intersect, setdiff, slice, union
The following objects are masked from ‘package:S4Vectors’:
first, intersect, rename, setdiff, setequal, union
The following objects are masked from ‘package:BiocGenerics’:
combine, intersect, setdiff, union
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library("ggrastr")
clean <- function (fn) {
fn <- gsub(pattern = ".+/", "", x = fn)
fn <- gsub(pattern = ".mm9.+", "", x = fn)
fn <- gsub(pattern = ".mm39.+", "", x = fn)
fn <- gsub(pattern = "_S.+", "", x = fn)
fn <- gsub(pattern = ".scaled.bw", "", x = fn)
fn <- gsub(pattern = ".unscaled.bw", "", x = fn)
fn <- gsub(pattern = "_batch2", "", x = fn)
fn <- gsub(pattern = "-", " ", x = fn)
fn <- gsub(pattern = "_", " ", x = fn)
fn <- gsub(pattern = " HA ", " ", x = fn)
fn <- gsub(pattern = "D1D6", "FANCJ-/-", x = fn)
fn <- gsub(pattern = "P2D2", "DHX36-/-", x = fn)
fn <- gsub(pattern = "P3D4", "FANCJ-/-DHX36-/-", x = fn)
return(fn)
}
BWs <- paste0(bw_dir,list.files(bw_dir,pattern="G4_.+R.\\.bw"))
mypal <-c("cornflowerblue","orange","red2","#505050")
mypal3 <-c("cornflowerblue","cornflowerblue","cornflowerblue","orange","orange","orange","red2","red2","red2","505050","505050","505050")
bw_granges_diff_analysis <- function(granges_c1,
granges_c2,
label_c1,
label_c2,
estimate_size_factors = FALSE,
as_granges = FALSE) {
# Bind first, get numbers after
names_values <- NULL
fields <- names(mcols(granges_c1))
if ("name" %in% fields) {
names_values <- mcols(granges_c1)[["name"]]
granges_c1 <- granges_c1[, fields[fields != "name"]]
}
fields <- names(mcols(granges_c2))
if ("name" %in% fields) {
granges_c2 <- granges_c2[, fields[fields != "name"]]
}
cts_df <- cbind(data.frame(granges_c1), mcols(granges_c2))
if (! is.null(names_values)) {
rownames(cts_df) <- names_values
}
# Needs to drop non-complete cases and match rows
complete <- complete.cases(cts_df)
cts_df <- cts_df[complete, ]
values_df <- cts_df[, 6:ncol(cts_df)] %>% dplyr::select(where(is.numeric))
cts <- get_nreads_columns(values_df)
condition_labels <- c(rep(label_c1, length(mcols(granges_c1))),
rep(label_c2, length(mcols(granges_c2))))
coldata <- data.frame(colnames(cts), condition = as.factor(condition_labels))
dds <- DESeq2::DESeqDataSetFromMatrix(countData = cts,
colData = coldata,
design = ~ condition,
rowRanges = granges_c1[complete, ])
if (estimate_size_factors == TRUE) {
dds <- DESeq2::estimateSizeFactors(dds)
}
else {
# Since files are scaled, we do not want to estimate size factors
sizeFactors(dds) <- c(rep(1, ncol(cts)))
}
dds <- DESeq2::estimateDispersions(dds)
dds <- DESeq2::nbinomWaldTest(dds)
if (as_granges) {
result <- DESeq2::results(dds, format = "GRanges",alpha = 0.01)
if (!is.null(names_values)) {
result$name <- names_values[complete]
}
}
else {
# result <- results(dds, format="DataFrame")
result <- dds
}
result
}
get_nreads_columns <- function(df, length_factor = 100) {
# Convert mean coverages to round integer read numbers
cts <- as.matrix(df)
cts <- as.matrix(cts[complete.cases(cts),])
cts <- round(cts*length_factor)
cts
}
peak_universe <- "../peaks/G4_combined_min3rep.bed"
BWs.WT <- BWs[grep("WT",BWs)]
BWs.FANCJ <- BWs[grep("D1D6",BWs)]
BWs.DHX36 <- BWs[grep("P2D2",BWs)]
BWs.DKO <- BWs[grep("P3D4",BWs)]
# Calculate here some loci or bins
cov.WT <- bw_loci(BWs.WT, loci = peak_universe)
Attaching package: ‘purrr’
The following object is masked from ‘package:GenomicRanges’:
reduce
The following object is masked from ‘package:IRanges’:
reduce
cov.DHX36 <- bw_loci(BWs.DHX36, loci = peak_universe)
cov.FANCJ <- bw_loci(BWs.FANCJ, loci = peak_universe)
cov.DKO <- bw_loci(BWs.DKO, loci = peak_universe)
cov.WT$name <- paste0("peak_",1:length(cov.WT))
cov.DHX36$name <- paste0("peak_",1:length(cov.DHX36))
cov.FANCJ$name <- paste0("peak_",1:length(cov.FANCJ))
cov.DKO$name <- paste0("peak_",1:length(cov.DKO))
diff_DHX36 <- bw_granges_diff_analysis(cov.WT, cov.DHX36,
"WT", "DHX36KO")
converting counts to integer mode
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
diff_FANCJ <- bw_granges_diff_analysis(cov.WT, cov.FANCJ,
"WT", "FANCJ")
converting counts to integer mode
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
diff_DKO <- bw_granges_diff_analysis(cov.WT, cov.DKO,
"WT", "DKO")
converting counts to integer mode
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
# This takes care of low conts and things like this, but you can also use
# diff_results as is for the things below
lfc_DHX36 <- DESeq2::lfcShrink(diff_DHX36, coef = "condition_WT_vs_DHX36KO", type="apeglm")
using 'apeglm' for LFC shrinkage. If used in published research, please cite:
Zhu, A., Ibrahim, J.G., Love, M.I. (2018) Heavy-tailed prior distributions for
sequence count data: removing the noise and preserving large differences.
Bioinformatics. https://doi.org/10.1093/bioinformatics/bty895
lfc_FANCJ <- DESeq2::lfcShrink(diff_FANCJ, coef = "condition_WT_vs_FANCJ", type="apeglm")
using 'apeglm' for LFC shrinkage. If used in published research, please cite:
Zhu, A., Ibrahim, J.G., Love, M.I. (2018) Heavy-tailed prior distributions for
sequence count data: removing the noise and preserving large differences.
Bioinformatics. https://doi.org/10.1093/bioinformatics/bty895
lfc_DKO <- DESeq2::lfcShrink(diff_DKO, coef = "condition_WT_vs_DKO", type="apeglm")
using 'apeglm' for LFC shrinkage. If used in published research, please cite:
Zhu, A., Ibrahim, J.G., Love, M.I. (2018) Heavy-tailed prior distributions for
sequence count data: removing the noise and preserving large differences.
Bioinformatics. https://doi.org/10.1093/bioinformatics/bty895
data_DHX36 <- plotMA(lfc_DHX36, returnData = T)
data_DHX36$lfc <- -data_DHX36$lfc
data_DHX36$mean <- log10(data_DHX36$mean)
data_FANCJ <- plotMA(lfc_FANCJ, returnData = T)
data_FANCJ$lfc <- -data_FANCJ$lfc
data_FANCJ$mean <- log10(data_FANCJ$mean)
data_DKO <- plotMA(lfc_DKO, returnData = T)
data_DKO$lfc <- -data_DKO$lfc
data_DKO$mean <- log10(data_DKO$mean)
ggscatter(data_DHX36,x ="mean",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[1])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5))
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.

plot_MA_DHX36 <- rasterize(last_plot(), layers='Point', dpi=600)
data_DHX36$cov.WT <- rowMeans(as.data.frame(cov.WT)[,6:8])
data_DHX36$cov.DHX36 <- rowMeans(as.data.frame(cov.DHX36)[,6:8])
ggscatter(data_DHX36,x ="cov.WT",y="cov.DHX36",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[1])) + scale_x_continuous(trans="log",limits = c(0.5,400)) + scale_y_continuous(trans="log",limits = c(0.5,400)) + geom_abline(slope = 1, linetype="dashed", size=0.1)

plot_XY_DHX36 <- rasterize(last_plot(), layers='Point', dpi=600)
data_DHX36$cov.WT <- rowMeans(as.data.frame(cov.WT)[,6:8])
data_DHX36$cov.DHX36 <- rowMeans(as.data.frame(cov.DHX36)[,6:8])
ggscatter(data_DHX36,x ="cov.WT",y="cov.DHX36",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[1])) + scale_x_continuous(limits = c(-10,50)) + scale_y_continuous(limits = c(-10,50)) + geom_abline(slope = 1, linetype="dashed", size=0.1)

plot_XY_DHX36_zoom <- rasterize(last_plot(), layers='Point', dpi=600)
ggscatter(data_FANCJ,x ="mean",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[2])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5))

plot_MA_FANCJ <- rasterize(last_plot(), layers='Point', dpi=600)
data_FANCJ$cov.WT <- rowMeans(as.data.frame(cov.WT)[,6:8])
data_FANCJ$cov.FANCJ <- rowMeans(as.data.frame(cov.FANCJ)[,6:8])
ggscatter(data_FANCJ,x ="cov.WT",y="cov.FANCJ",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[2])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + scale_x_continuous(trans="log",limits = c(0.5,400)) + scale_y_continuous(trans="log",limits = c(0.5,400)) + geom_abline(slope = 1, linetype="dashed", size=0.1)

plot_XY_FANCJ <- rasterize(last_plot(), layers='Point', dpi=600)
ggscatter(data_DKO,x ="mean",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[3])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5))

plot_MA_DKO <- rasterize(last_plot(), layers='Point', dpi=600)
data_DKO$cov.WT <- rowMeans(as.data.frame(cov.WT)[,6:8])
data_DKO$cov.DKO <- rowMeans(as.data.frame(cov.DKO)[,6:8])
ggscatter(data_DKO,x ="cov.WT",y="cov.DKO",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[3])) + geom_hline(yintercept = 0, linetype="dashed", size=0.1) + scale_x_continuous(trans="log",limits = c(0.5,400)) + scale_y_continuous(trans="log",limits = c(0.5,400)) + geom_abline(slope = 1, linetype="dashed", size=0.1)

plot_XY_DKO <- rasterize(last_plot(), layers='Point', dpi=600)
data_DKO$lfc_DHX36 <- data_DHX36$lfc
data_DKO$lfc_FANCJ <- data_FANCJ$lfc
ggscatter(data_DKO,x ="lfc_DHX36",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[3]))+ geom_hline(yintercept = 0, linetype="dashed", size=0.1) + geom_vline(xintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5), xlim=c(-5,5))

plot_LFC_DKO_vs_DHX36 <- rasterize(last_plot(), layers='Point', dpi=600)
ggscatter(data_DKO,x ="lfc_FANCJ",y="lfc",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[3]))+ geom_hline(yintercept = 0, linetype="dashed", size=0.1) + geom_vline(xintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5), xlim=c(-5,5))

plot_LFC_DKO_vs_FANCJ <- rasterize(last_plot(), layers='Point', dpi=600)
data_DHX36$lfc_DKO <- data_DKO$lfc
ggscatter(data_DHX36,x ="lfc",y="lfc_DKO",color="isDE",size = 0.8, alpha=0.5, palette = c("gray",mypal[1]))+ geom_hline(yintercept = 0, linetype="dashed", size=0.1) + geom_vline(xintercept = 0, linetype="dashed", size=0.1) + coord_cartesian(ylim=c(-5,5), xlim=c(-5,5))

bed <- as.data.frame(cov.DHX36)[,1:3]
results_table <- data.frame(chr=bed$seqnames,start=bed$start,end=bed$end,name=cov.WT$name, baseMean=lfc_DKO$baseMean,DHX36=data_DHX36$isDE,FANCJ=data_FANCJ$isDE,DKO=data_DKO$isDE,DHX36lfc=data_DHX36$lfc,FANCJlfc=data_FANCJ$lfc,DKOlfc=data_DKO$lfc,dir=".")
results_table$nonsig <- !(results_table$DHX36 | results_table$FANCJ | results_table$DKO)
results_table$sig <- factor("lowlfc", levels=c("nonsig","lowlfc","FANCJ","DHX36","DKO"))
results_table$sig[(results_table$nonsig)] <- "nonsig"
results_table$sig[(results_table$DKO & results_table$DKOlfc>1)] <- "DKO"
results_table$sig[(results_table$DHX36 & results_table$DHX36lfc>1)] <- "DHX36"
results_table$sig[(results_table$FANCJ & results_table$FANCJlfc>1)] <- "FANCJ"
write.table(results_table,"G4_CnT_combined_peaks_DESeq_results.txt", row.names = F, col.names = T,quote = F, sep = "\t")
DHX36_bed <- results_table[(results_table$DHX36 & results_table$DHX36lfc>1),c(1,2,3,4,9,12)]
write.table(DHX36_bed,"../peaks/G4_CnT_combined_peaks_DESeq_DHX36_sig.bed", row.names = F, col.names = F,quote = F, sep = "\t")
FANCJ_bed <- results_table[(results_table$FANCJ & results_table$FANCJlfc>1),c(1,2,3,4,10,12)]
write.table(FANCJ_bed,"../peaks/G4_CnT_combined_peaks_DESeq_FANCJ_sig.bed", row.names = F, col.names = F,quote = F, sep = "\t")
DKO_bed <- results_table[(results_table$DKO & results_table$DKOlfc>1),c(1,2,3,4,11,12)]
write.table(DKO_bed,"../peaks/G4_CnT_combined_peaks_DESeq_DKO_sig.bed", row.names = F, col.names = F,quote = F, sep = "\t")
nonsig_bed <- results_table[results_table$nonsig ,c(1,2,3,4,11,12)]
write.table(nonsig_bed,"../peaks/G4_CnT_combined_peaks_DESeq_nonsig.bed", row.names = F, col.names = F,quote = F, sep = "\t")
DKO_bed_top <- results_table[(results_table$DKO==TRUE & results_table$DKOlfc>2 & results_table$baseMean > 100),c(1,2,3,4,11,12)]
write.table(DKO_bed_top,"../peaks/G4_CnT_combined_peaks_DESeq_DKO_sig_lfc_base_cutoff.bed", row.names = F, col.names = F,quote = F, sep = "\t")
write.table(cbind(results_table[,c(1,2,3)],results_table$sig,as.numeric(results_table$sig),"."),"../peaks/G4_CnT_combined_peaks_DESeq_sig_categories.bed", row.names = F, col.names = F,quote = F, sep = "\t")
library(eulerr)
v <- list(DHX36=DHX36_bed$name,FANCJ=FANCJ_bed$name,DKO=DKO_bed$name)
plot_Venn_all <- plot(euler(v),quantities=T, border="black")
plot_Venn_all

library(eulerr)
DKOneg <- results_table[(results_table$DKO==TRUE & results_table$DKOlfc< -1),c(4)]
v <- list(all=cov.WT$name,DKOneg=DKOneg,DKO=DKO_bed$name)
plot_Venn_DKO <- plot(euler(v),quantities=T)
plot_Venn_DKO

dir.create("./plots",showWarnings = F)
ggsave("plots/peaks_DESeq2_MA_DHX36.pdf",plot_MA_DHX36,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_MA_FANCJ.pdf",plot_MA_FANCJ,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_MA_DKO.pdf",plot_MA_DKO,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_LFC_DHX36.pdf",plot_LFC_DKO_vs_DHX36,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_LFC_FANCJ.pdf",plot_LFC_DKO_vs_FANCJ,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_Venn_KOs.pdf",plot_Venn_all,width = 4, height= 4)
ggsave("plots/peaks_DESeq2_Venn_DKO_vs_all.pdf",plot_Venn_DKO,width = 4, height= 4)
library(cowplot)
Attaching package: ‘cowplot’
The following object is masked from ‘package:ggpubr’:
get_legend
dir.create("./panels",showWarnings = F)
library("cowplot")
p <- ggdraw() +
draw_plot(plot_MA_DHX36, x = 0, y = 0.5, width = .33, height = .5) +
draw_plot(plot_MA_FANCJ, x = .33, y = 0.5, width = .33, height = .5) +
draw_plot(plot_MA_DKO, x = 0.66, y = 0.5, width = .33, height = 0.5) +
draw_plot(plot_LFC_DKO_vs_DHX36, x = 0, y = 0, width = 0.33, height = 0.5) +
draw_plot(plot_LFC_DKO_vs_FANCJ, x = 0.33, y = 0, width = 0.33, height = 0.5) +
draw_plot(plot_Venn_all, x = 0.66, y = 0, width = 0.33, height = 0.5) +
draw_plot_label(label = c("a", "b", "c","d","e","f"), size = 15,
x = c(0, 0.33, 0.66, 0, 0.33, 0.66), y = c(1, 1, 1, 0.5, 0.5, 0.5))
p

ggsave("panels/peaks_DESeq2.pdf",p)
Saving 12 x 8 in image
library(cowplot)
dir.create("./panels",showWarnings = F)
library("cowplot")
p <- ggdraw() +
draw_plot(plot_MA_DHX36, x = 0, y = 0.5, width = .33, height = .5) +
draw_plot(plot_MA_FANCJ, x = .33, y = 0.5, width = .33, height = .5) +
draw_plot(plot_MA_DKO, x = 0.66, y = 0.5, width = .33, height = 0.5) +
draw_plot(plot_XY_DHX36, x = 0, y = 0, width = 0.33, height = 0.5) +
draw_plot(plot_XY_FANCJ, x = 0.33, y = 0, width = 0.33, height = 0.5) +
draw_plot(plot_XY_DKO, x = 0.66, y = 0, width = 0.33, height = 0.5) +
draw_plot_label(label = c("a", "b", "c","d","e","f"), size = 15,
x = c(0, 0.33, 0.66, 0, 0.33, 0.66), y = c(1, 1, 1, 0.5, 0.5, 0.5))
Warning: Removed 36 rows containing missing values or values outside the scale range (`geom_point()`).Warning: log-2.718282 transformation introduced infinite values.Warning: Removed 22 rows containing missing values or values outside the scale range (`geom_point()`).Warning: log-2.718282 transformation introduced infinite values.Warning: Removed 38 rows containing missing values or values outside the scale range (`geom_point()`).
p

ggsave("panels/peaks_DESeq2_scatter.pdf",p)
Saving 12 x 8 in image
cov <- cbind( as.data.frame(cov.WT)[,1:8],
as.data.frame(cov.DHX36)[,6:8],
as.data.frame(cov.FANCJ)[,6:8],
as.data.frame(cov.DKO)[,6:8])
colnames(cov) <- c(colnames(cov)[1:5],"WT1","WT2","WT3","DHX1","DHX2","DHX3","FAN1","FAN2","FAN3","DKO1","DKO2","DKO3")
rownames(cov) <- as.data.frame(cov.WT)$name
cov$DHX36_sig <- rownames(cov) %in% DHX36_bed$name
cov$FANCJ_sig <- rownames(cov) %in% FANCJ_bed$name
cov$DKO_sig <- rownames(cov) %in% DKO_bed$name
cov$non_sig <- with(cov, !(DHX36_sig | FANCJ_sig | DKO_sig))
library(reshape2)
mdf <- melt(data.frame(name=rownames(cov),cov[,6:21]))
Using name, DHX36_sig, FANCJ_sig, DKO_sig, non_sig as id variables
mdf <- mdf[mdf$value<500,]
mdf$cond <- "WT"
mdf$cond[grep("DHX",mdf$variable)] <- "DHX36-/-"
mdf$cond[grep("FAN",mdf$variable)] <- "FANCJ-/-"
mdf$cond[grep("DKO",mdf$variable)] <- "DHX36-/-FANCJ-/-"
plot_viol_rep_all_peaks <- ggviolin(mdf, x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,50))
plot_viol_rep_all_peaks

plot_viol_rep_DHX36_peaks <- ggviolin(mdf[mdf$DHX36_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,50))
plot_viol_rep_DHX36_peaks

ggviolin(mdf[mdf$FANCJ_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,50))

plot_viol_rep_DKO_peaks <- ggviolin(mdf[mdf$DKO_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,50))
plot_viol_rep_DKO_peaks

plot_viol_rep_nonsig_peaks <- ggviolin(mdf[mdf$non_sig,], x="variable",y="value",fill="cond",palette = mypal, add="mean_sd") +
coord_cartesian(ylim=c(0,50))
plot_viol_rep_nonsig_peaks

ggsave("plots/peaks_DESeq2_viol_rep_all.pdf",plot_viol_rep_all_peaks)
Saving 7 x 7 in image
ggsave("plots/peaks_DESeq2_viol_rep_DKO.pdf",plot_viol_rep_DKO_peaks)
ggsave("plots/peaks_DESeq2_viol_rep_DHX36.pdf",plot_viol_rep_DHX36_peaks)
ggsave("plots/peaks_DESeq2_viol_rep_nonsig.pdf",plot_viol_rep_nonsig_peaks)
sdf <- aggregate(value ~ name + cond, data=mdf, FUN="mean")
sdf$cond <- factor(sdf$cond,levels=c("WT","DHX36-/-","FANCJ-/-","DHX36-/-FANCJ-/-"))
ggviolin(sdf, x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,50))

sdf$DHX36_sig <- sdf$name %in% DHX36_bed$name
sdf$FANCJ_sig <- sdf$name %in% FANCJ_bed$name
sdf$DKO_sig <- sdf$name %in% DKO_bed$name
sdf$DKO_top <- sdf$name %in% DKO_bed_top$name
ggviolin(sdf[sdf$DHX36,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))

ggviolin(sdf[sdf$FANCJ_sig,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))

plot_viol_DKO_peaks <- ggviolin(sdf[sdf$DKO_sig,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))
plot_viol_DKO_peaks

ggviolin(sdf[sdf$DKO_top,], x="cond",y="value",fill="cond",palette = mypal[c(4,1,2,3)], add="mean_sd") +
coord_cartesian(ylim=c(0,75))

LS0tCnRpdGxlOiAiRzQgQ1VUJlRhZyBhbmFseXNpcyBtRVNDIChXVCwgRkFOQ0ogS08sIERIWDM2IEtPLCBES08pIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpTaW1vbiBFbHPDpHNzZXIsIEthcm9saW5za2EgSW5zdGl0dXRldCAoMjAyMykKCiMjIyBERVNlcTIgYW5hbHlzaXMgb2YgcGVhayB1bml2ZXJzZSAoam9pbnQgcGVhayBzZXQgY2FsbGVkIGluIGFueSBjb25kaXRpb24sIG11c3QgYmUgY2FsbGVkIGluIGFsbCB0aHJlZSByZXBsaWNhdGVzLCBNQUNTMykKCgpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0zfQpid19kaXIgPC0gIi9Wb2x1bWVzL0RBVEEvREFUQS9QdWNrL2JpZ3dpZy8iCmNocm9taG1tIDwtICIuLi9nZW5vbWUvRVNDXzEwX3NlZ21lbnRzLm1tMzkuYmVkIgoKbGlicmFyeSgid2lnZ2xlc2NvdXQiKQpsaWJyYXJ5KCJnZ3B1YnIiKQpsaWJyYXJ5KCJnZ3Bsb3QyIikKbGlicmFyeSgiREVTZXEyIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJnZ3Jhc3RyIikKbGlicmFyeSgicmVzaGFwZTIiKQoKY2xlYW4gPC0gZnVuY3Rpb24gKGZuKSB7CiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIi4rLyIsICIiLCB4ID0gZm4pCiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIi5tbTkuKyIsICIiLCB4ID0gZm4pCiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIi5tbTM5LisiLCAiIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICJfUy4rIiwgIiIsIHggPSBmbikKICBmbiA8LSBnc3ViKHBhdHRlcm4gPSAiLnNjYWxlZC5idyIsICIiLCB4ID0gZm4pCiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIi51bnNjYWxlZC5idyIsICIiLCB4ID0gZm4pCiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIl9iYXRjaDIiLCAiIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICItIiwgIiAiLCB4ID0gZm4pCiAgZm4gPC0gZ3N1YihwYXR0ZXJuID0gIl8iLCAiICIsIHggPSBmbikKICBmbiA8LSBnc3ViKHBhdHRlcm4gPSAiIEhBICIsICIgIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICJEMUQ2IiwgIkZBTkNKLS8tIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICJQMkQyIiwgIkRIWDM2LS8tIiwgeCA9IGZuKQogIGZuIDwtIGdzdWIocGF0dGVybiA9ICJQM0Q0IiwgIkZBTkNKLS8tREhYMzYtLy0iLCB4ID0gZm4pCiAgcmV0dXJuKGZuKQp9CgpCV3MgPC0gcGFzdGUwKGJ3X2RpcixsaXN0LmZpbGVzKGJ3X2RpcixwYXR0ZXJuPSJHNF8uK1IuXFwuYnciKSkKCm15cGFsIDwtYygiY29ybmZsb3dlcmJsdWUiLCJvcmFuZ2UiLCJyZWQyIiwiIzUwNTA1MCIpCm15cGFsMyA8LWMoImNvcm5mbG93ZXJibHVlIiwiY29ybmZsb3dlcmJsdWUiLCJjb3JuZmxvd2VyYmx1ZSIsIm9yYW5nZSIsIm9yYW5nZSIsIm9yYW5nZSIsInJlZDIiLCJyZWQyIiwicmVkMiIsIjUwNTA1MCIsIjUwNTA1MCIsIjUwNTA1MCIpCmBgYAoKYGBge3J9CmJ3X2dyYW5nZXNfZGlmZl9hbmFseXNpcyA8LSBmdW5jdGlvbihncmFuZ2VzX2MxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3Jhbmdlc19jMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX2MxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxfYzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0ZV9zaXplX2ZhY3RvcnMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzX2dyYW5nZXMgPSBGQUxTRSkgewoKICAjIEJpbmQgZmlyc3QsIGdldCBudW1iZXJzIGFmdGVyCiAgbmFtZXNfdmFsdWVzIDwtIE5VTEwKICBmaWVsZHMgPC0gbmFtZXMobWNvbHMoZ3Jhbmdlc19jMSkpCgogIGlmICgibmFtZSIgJWluJSBmaWVsZHMpIHsKICAgIG5hbWVzX3ZhbHVlcyA8LSBtY29scyhncmFuZ2VzX2MxKVtbIm5hbWUiXV0KICAgIGdyYW5nZXNfYzEgPC0gZ3Jhbmdlc19jMVssIGZpZWxkc1tmaWVsZHMgIT0gIm5hbWUiXV0KICB9CgogIGZpZWxkcyA8LSBuYW1lcyhtY29scyhncmFuZ2VzX2MyKSkKICBpZiAoIm5hbWUiICVpbiUgZmllbGRzKSB7CiAgICBncmFuZ2VzX2MyIDwtIGdyYW5nZXNfYzJbLCBmaWVsZHNbZmllbGRzICE9ICJuYW1lIl1dCiAgfQoKICBjdHNfZGYgPC0gY2JpbmQoZGF0YS5mcmFtZShncmFuZ2VzX2MxKSwgbWNvbHMoZ3Jhbmdlc19jMikpCgogIGlmICghIGlzLm51bGwobmFtZXNfdmFsdWVzKSkgewogICAgcm93bmFtZXMoY3RzX2RmKSA8LSBuYW1lc192YWx1ZXMKICB9CgogICMgTmVlZHMgdG8gZHJvcCBub24tY29tcGxldGUgY2FzZXMgYW5kIG1hdGNoIHJvd3MKICBjb21wbGV0ZSA8LSBjb21wbGV0ZS5jYXNlcyhjdHNfZGYpCiAgY3RzX2RmIDwtIGN0c19kZltjb21wbGV0ZSwgXQoKICB2YWx1ZXNfZGYgPC0gY3RzX2RmWywgNjpuY29sKGN0c19kZildICU+JSBkcGx5cjo6c2VsZWN0KHdoZXJlKGlzLm51bWVyaWMpKQogIGN0cyA8LSBnZXRfbnJlYWRzX2NvbHVtbnModmFsdWVzX2RmKQoKICBjb25kaXRpb25fbGFiZWxzIDwtIGMocmVwKGxhYmVsX2MxLCBsZW5ndGgobWNvbHMoZ3Jhbmdlc19jMSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgcmVwKGxhYmVsX2MyLCBsZW5ndGgobWNvbHMoZ3Jhbmdlc19jMikpKSkKCgogIGNvbGRhdGEgPC0gZGF0YS5mcmFtZShjb2xuYW1lcyhjdHMpLCBjb25kaXRpb24gPSBhcy5mYWN0b3IoY29uZGl0aW9uX2xhYmVscykpCgogIGRkcyA8LSBERVNlcTI6OkRFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhID0gY3RzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBjb2xkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH4gY29uZGl0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd1JhbmdlcyA9IGdyYW5nZXNfYzFbY29tcGxldGUsIF0pCgoKICBpZiAoZXN0aW1hdGVfc2l6ZV9mYWN0b3JzID09IFRSVUUpIHsKICAgIGRkcyA8LSBERVNlcTI6OmVzdGltYXRlU2l6ZUZhY3RvcnMoZGRzKQogIH0KICBlbHNlIHsKICAgICMgU2luY2UgZmlsZXMgYXJlIHNjYWxlZCwgd2UgZG8gbm90IHdhbnQgdG8gZXN0aW1hdGUgc2l6ZSBmYWN0b3JzCiAgICBzaXplRmFjdG9ycyhkZHMpIDwtIGMocmVwKDEsIG5jb2woY3RzKSkpCiAgfQoKICBkZHMgPC0gREVTZXEyOjplc3RpbWF0ZURpc3BlcnNpb25zKGRkcykKICBkZHMgPC0gREVTZXEyOjpuYmlub21XYWxkVGVzdChkZHMpCgogIGlmIChhc19ncmFuZ2VzKSB7CiAgICByZXN1bHQgPC0gREVTZXEyOjpyZXN1bHRzKGRkcywgZm9ybWF0ID0gIkdSYW5nZXMiLGFscGhhID0gMC4wMSkKICAgIGlmICghaXMubnVsbChuYW1lc192YWx1ZXMpKSB7CiAgICAgIHJlc3VsdCRuYW1lIDwtIG5hbWVzX3ZhbHVlc1tjb21wbGV0ZV0KICAgIH0KCiAgfQogIGVsc2UgewogICAgIyByZXN1bHQgPC0gcmVzdWx0cyhkZHMsIGZvcm1hdD0iRGF0YUZyYW1lIikKICAgIHJlc3VsdCA8LSBkZHMKICB9CgogIHJlc3VsdAp9CgpnZXRfbnJlYWRzX2NvbHVtbnMgPC0gZnVuY3Rpb24oZGYsIGxlbmd0aF9mYWN0b3IgPSAxMDApIHsKICAjIENvbnZlcnQgbWVhbiBjb3ZlcmFnZXMgdG8gcm91bmQgaW50ZWdlciByZWFkIG51bWJlcnMKICBjdHMgPC0gYXMubWF0cml4KGRmKQogIGN0cyA8LSBhcy5tYXRyaXgoY3RzW2NvbXBsZXRlLmNhc2VzKGN0cyksXSkKICBjdHMgPC0gcm91bmQoY3RzKmxlbmd0aF9mYWN0b3IpCiAgY3RzCn0KYGBgCgpgYGB7cn0KCnBlYWtfdW5pdmVyc2UgPC0gIi4uL3BlYWtzL0c0X2NvbWJpbmVkX21pbjNyZXAuYmVkIgoKQldzLldUIDwtIEJXc1tncmVwKCJXVCIsQldzKV0KQldzLkZBTkNKIDwtIEJXc1tncmVwKCJEMUQ2IixCV3MpXQpCV3MuREhYMzYgPC0gQldzW2dyZXAoIlAyRDIiLEJXcyldCkJXcy5ES08gPC0gQldzW2dyZXAoIlAzRDQiLEJXcyldCiAgCiMgQ2FsY3VsYXRlIGhlcmUgc29tZSBsb2NpIG9yIGJpbnMKY292LldUIDwtIGJ3X2xvY2koQldzLldULCBsb2NpID0gcGVha191bml2ZXJzZSkKY292LkRIWDM2IDwtIGJ3X2xvY2koQldzLkRIWDM2LCBsb2NpID0gcGVha191bml2ZXJzZSkKY292LkZBTkNKIDwtIGJ3X2xvY2koQldzLkZBTkNKLCBsb2NpID0gcGVha191bml2ZXJzZSkKY292LkRLTyA8LSBid19sb2NpKEJXcy5ES08sIGxvY2kgPSBwZWFrX3VuaXZlcnNlKQoKY292LldUJG5hbWUgPC0gcGFzdGUwKCJwZWFrXyIsMTpsZW5ndGgoY292LldUKSkKY292LkRIWDM2JG5hbWUgPC0gcGFzdGUwKCJwZWFrXyIsMTpsZW5ndGgoY292LkRIWDM2KSkKY292LkZBTkNKJG5hbWUgPC0gcGFzdGUwKCJwZWFrXyIsMTpsZW5ndGgoY292LkZBTkNKKSkKY292LkRLTyRuYW1lIDwtIHBhc3RlMCgicGVha18iLDE6bGVuZ3RoKGNvdi5ES08pKQpgYGAKCmBgYHtyfQpkaWZmX0RIWDM2IDwtIGJ3X2dyYW5nZXNfZGlmZl9hbmFseXNpcyhjb3YuV1QsIGNvdi5ESFgzNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXVCIsICJESFgzNktPIikKZGlmZl9GQU5DSiA8LSBid19ncmFuZ2VzX2RpZmZfYW5hbHlzaXMoY292LldULCBjb3YuRkFOQ0osCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV1QiLCAiRkFOQ0oiKQpkaWZmX0RLTyA8LSBid19ncmFuZ2VzX2RpZmZfYW5hbHlzaXMoY292LldULCBjb3YuREtPLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldUIiwgIkRLTyIpCgoKIyBUaGlzIHRha2VzIGNhcmUgb2YgbG93IGNvbnRzIGFuZCB0aGluZ3MgbGlrZSB0aGlzLCBidXQgeW91IGNhbiBhbHNvIHVzZQojIGRpZmZfcmVzdWx0cyBhcyBpcyBmb3IgdGhlIHRoaW5ncyBiZWxvdwpsZmNfREhYMzYgPC0gREVTZXEyOjpsZmNTaHJpbmsoZGlmZl9ESFgzNiwgY29lZiA9ICJjb25kaXRpb25fV1RfdnNfREhYMzZLTyIsIHR5cGU9ImFwZWdsbSIpCmxmY19GQU5DSiA8LSBERVNlcTI6OmxmY1NocmluayhkaWZmX0ZBTkNKLCBjb2VmID0gImNvbmRpdGlvbl9XVF92c19GQU5DSiIsIHR5cGU9ImFwZWdsbSIpCmxmY19ES08gPC0gREVTZXEyOjpsZmNTaHJpbmsoZGlmZl9ES08sIGNvZWYgPSAiY29uZGl0aW9uX1dUX3ZzX0RLTyIsIHR5cGU9ImFwZWdsbSIpCgpkYXRhX0RIWDM2IDwtIHBsb3RNQShsZmNfREhYMzYsIHJldHVybkRhdGEgPSBUKQpkYXRhX0RIWDM2JGxmYyA8LSAtZGF0YV9ESFgzNiRsZmMKZGF0YV9ESFgzNiRtZWFuIDwtIGxvZzEwKGRhdGFfREhYMzYkbWVhbikKCmRhdGFfRkFOQ0ogPC0gcGxvdE1BKGxmY19GQU5DSiwgcmV0dXJuRGF0YSA9IFQpCmRhdGFfRkFOQ0okbGZjIDwtIC1kYXRhX0ZBTkNKJGxmYwpkYXRhX0ZBTkNKJG1lYW4gPC0gbG9nMTAoZGF0YV9GQU5DSiRtZWFuKQoKZGF0YV9ES08gPC0gcGxvdE1BKGxmY19ES08sIHJldHVybkRhdGEgPSBUKQpkYXRhX0RLTyRsZmMgPC0gLWRhdGFfREtPJGxmYwpkYXRhX0RLTyRtZWFuIDwtIGxvZzEwKGRhdGFfREtPJG1lYW4pCmBgYAoKCmBgYHtyIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9Cmdnc2NhdHRlcihkYXRhX0RIWDM2LHggPSJtZWFuIix5PSJsZmMiLGNvbG9yPSJpc0RFIixzaXplID0gMC44LCBhbHBoYT0wLjUsIHBhbGV0dGUgPSBjKCJncmF5IixteXBhbFsxXSkpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoLTUsNSkpCnBsb3RfTUFfREhYMzYgPC0gcmFzdGVyaXplKGxhc3RfcGxvdCgpLCBsYXllcnM9J1BvaW50JywgZHBpPTYwMCkgCmBgYApgYGB7ciBmaWcud2lkdGg9MiwgZmlnLmhlaWdodD0yfQpkYXRhX0RIWDM2JGNvdi5XVCA8LSByb3dNZWFucyhhcy5kYXRhLmZyYW1lKGNvdi5XVClbLDY6OF0pCmRhdGFfREhYMzYkY292LkRIWDM2IDwtIHJvd01lYW5zKGFzLmRhdGEuZnJhbWUoY292LkRIWDM2KVssNjo4XSkKZ2dzY2F0dGVyKGRhdGFfREhYMzYseCA9ImNvdi5XVCIseT0iY292LkRIWDM2Iixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbMV0pKSArIHNjYWxlX3hfY29udGludW91cyh0cmFucz0ibG9nIixsaW1pdHMgPSBjKDAuNSw0MDApKSArIHNjYWxlX3lfY29udGludW91cyh0cmFucz0ibG9nIixsaW1pdHMgPSBjKDAuNSw0MDApKSArIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKQpwbG90X1hZX0RIWDM2IDwtIHJhc3Rlcml6ZShsYXN0X3Bsb3QoKSwgbGF5ZXJzPSdQb2ludCcsIGRwaT02MDApIApgYGAKYGBge3IgZmlnLndpZHRoPTIsIGZpZy5oZWlnaHQ9Mn0KZGF0YV9ESFgzNiRjb3YuV1QgPC0gcm93TWVhbnMoYXMuZGF0YS5mcmFtZShjb3YuV1QpWyw2OjhdKQpkYXRhX0RIWDM2JGNvdi5ESFgzNiA8LSByb3dNZWFucyhhcy5kYXRhLmZyYW1lKGNvdi5ESFgzNilbLDY6OF0pCmdnc2NhdHRlcihkYXRhX0RIWDM2LHggPSJjb3YuV1QiLHk9ImNvdi5ESFgzNiIsY29sb3I9ImlzREUiLHNpemUgPSAwLjgsIGFscGhhPTAuNSwgcGFsZXR0ZSA9IGMoImdyYXkiLG15cGFsWzFdKSkgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTAsNTApKSArIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC0xMCw1MCkpICsgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBsaW5ldHlwZT0iZGFzaGVkIiwgc2l6ZT0wLjEpCnBsb3RfWFlfREhYMzZfem9vbSA8LSByYXN0ZXJpemUobGFzdF9wbG90KCksIGxheWVycz0nUG9pbnQnLCBkcGk9NjAwKSAKYGBgCgpgYGB7ciBmaWcud2lkdGg9MiwgZmlnLmhlaWdodD0yfQpnZ3NjYXR0ZXIoZGF0YV9GQU5DSix4ID0ibWVhbiIseT0ibGZjIixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbMl0pKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC01LDUpKQpwbG90X01BX0ZBTkNKIDwtIHJhc3Rlcml6ZShsYXN0X3Bsb3QoKSwgbGF5ZXJzPSdQb2ludCcsIGRwaT02MDApIApgYGAKCmBgYHtyIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9CmRhdGFfRkFOQ0okY292LldUIDwtIHJvd01lYW5zKGFzLmRhdGEuZnJhbWUoY292LldUKVssNjo4XSkKZGF0YV9GQU5DSiRjb3YuRkFOQ0ogPC0gcm93TWVhbnMoYXMuZGF0YS5mcmFtZShjb3YuRkFOQ0opWyw2OjhdKQpnZ3NjYXR0ZXIoZGF0YV9GQU5DSix4ID0iY292LldUIix5PSJjb3YuRkFOQ0oiLGNvbG9yPSJpc0RFIixzaXplID0gMC44LCBhbHBoYT0wLjUsIHBhbGV0dGUgPSBjKCJncmF5IixteXBhbFsyXSkpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIHNjYWxlX3hfY29udGludW91cyh0cmFucz0ibG9nIixsaW1pdHMgPSBjKDAuNSw0MDApKSArIHNjYWxlX3lfY29udGludW91cyh0cmFucz0ibG9nIixsaW1pdHMgPSBjKDAuNSw0MDApKSArIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKQpwbG90X1hZX0ZBTkNKIDwtIHJhc3Rlcml6ZShsYXN0X3Bsb3QoKSwgbGF5ZXJzPSdQb2ludCcsIGRwaT02MDApIApgYGAKCmBgYHtyIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9Cmdnc2NhdHRlcihkYXRhX0RLTyx4ID0ibWVhbiIseT0ibGZjIixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbM10pKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC01LDUpKQpwbG90X01BX0RLTyA8LSByYXN0ZXJpemUobGFzdF9wbG90KCksIGxheWVycz0nUG9pbnQnLCBkcGk9NjAwKSAKYGBgCgpgYGB7ciBmaWcud2lkdGg9MiwgZmlnLmhlaWdodD0yfQpkYXRhX0RLTyRjb3YuV1QgPC0gcm93TWVhbnMoYXMuZGF0YS5mcmFtZShjb3YuV1QpWyw2OjhdKQpkYXRhX0RLTyRjb3YuREtPIDwtIHJvd01lYW5zKGFzLmRhdGEuZnJhbWUoY292LkRLTylbLDY6OF0pCmdnc2NhdHRlcihkYXRhX0RLTyx4ID0iY292LldUIix5PSJjb3YuREtPIixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbM10pKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBzY2FsZV94X2NvbnRpbnVvdXModHJhbnM9ImxvZyIsbGltaXRzID0gYygwLjUsNDAwKSkgKyBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9ImxvZyIsbGltaXRzID0gYygwLjUsNDAwKSkgKyBnZW9tX2FibGluZShzbG9wZSA9IDEsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkKcGxvdF9YWV9ES08gPC0gcmFzdGVyaXplKGxhc3RfcGxvdCgpLCBsYXllcnM9J1BvaW50JywgZHBpPTYwMCkgCmBgYAoKYGBge3IgZmlnLndpZHRoPTIsIGZpZy5oZWlnaHQ9Mn0KZGF0YV9ES08kbGZjX0RIWDM2IDwtIGRhdGFfREhYMzYkbGZjCmRhdGFfREtPJGxmY19GQU5DSiA8LSBkYXRhX0ZBTkNKJGxmYwpnZ3NjYXR0ZXIoZGF0YV9ES08seCA9ImxmY19ESFgzNiIseT0ibGZjIixjb2xvcj0iaXNERSIsc2l6ZSA9IDAuOCwgYWxwaGE9MC41LCBwYWxldHRlID0gYygiZ3JheSIsbXlwYWxbM10pKSsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIHNpemU9MC4xKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKC01LDUpLCB4bGltPWMoLTUsNSkpCnBsb3RfTEZDX0RLT192c19ESFgzNiA8LSByYXN0ZXJpemUobGFzdF9wbG90KCksIGxheWVycz0nUG9pbnQnLCBkcGk9NjAwKQpgYGAKYGBge3IgZmlnLndpZHRoPTIsIGZpZy5oZWlnaHQ9Mn0KZ2dzY2F0dGVyKGRhdGFfREtPLHggPSJsZmNfRkFOQ0oiLHk9ImxmYyIsY29sb3I9ImlzREUiLHNpemUgPSAwLjgsIGFscGhhPTAuNSwgcGFsZXR0ZSA9IGMoImdyYXkiLG15cGFsWzNdKSkrIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0iZGFzaGVkIiwgc2l6ZT0wLjEpICsgY29vcmRfY2FydGVzaWFuKHlsaW09YygtNSw1KSwgeGxpbT1jKC01LDUpKQpwbG90X0xGQ19ES09fdnNfRkFOQ0ogPC0gcmFzdGVyaXplKGxhc3RfcGxvdCgpLCBsYXllcnM9J1BvaW50JywgZHBpPTYwMCkKYGBgCmBgYHtyIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9CmRhdGFfREhYMzYkbGZjX0RLTyA8LSBkYXRhX0RLTyRsZmMKZ2dzY2F0dGVyKGRhdGFfREhYMzYseCA9ImxmYyIseT0ibGZjX0RLTyIsY29sb3I9ImlzREUiLHNpemUgPSAwLjgsIGFscGhhPTAuNSwgcGFsZXR0ZSA9IGMoImdyYXkiLG15cGFsWzFdKSkrIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBzaXplPTAuMSkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0iZGFzaGVkIiwgc2l6ZT0wLjEpICsgY29vcmRfY2FydGVzaWFuKHlsaW09YygtNSw1KSwgeGxpbT1jKC01LDUpKQpgYGAKCmBgYHtyfQpiZWQgPC0gYXMuZGF0YS5mcmFtZShjb3YuREhYMzYpWywxOjNdCgpyZXN1bHRzX3RhYmxlIDwtIGRhdGEuZnJhbWUoY2hyPWJlZCRzZXFuYW1lcyxzdGFydD1iZWQkc3RhcnQsZW5kPWJlZCRlbmQsbmFtZT1jb3YuV1QkbmFtZSwgYmFzZU1lYW49bGZjX0RLTyRiYXNlTWVhbixESFgzNj1kYXRhX0RIWDM2JGlzREUsRkFOQ0o9ZGF0YV9GQU5DSiRpc0RFLERLTz1kYXRhX0RLTyRpc0RFLERIWDM2bGZjPWRhdGFfREhYMzYkbGZjLEZBTkNKbGZjPWRhdGFfRkFOQ0okbGZjLERLT2xmYz1kYXRhX0RLTyRsZmMsZGlyPSIuIikKCnJlc3VsdHNfdGFibGUkbm9uc2lnIDwtICEocmVzdWx0c190YWJsZSRESFgzNiB8IHJlc3VsdHNfdGFibGUkRkFOQ0ogfCByZXN1bHRzX3RhYmxlJERLTykKCnJlc3VsdHNfdGFibGUkc2lnIDwtIGZhY3RvcigibG93bGZjIiwgbGV2ZWxzPWMoIm5vbnNpZyIsImxvd2xmYyIsIkZBTkNKIiwiREhYMzYiLCJES08iKSkKcmVzdWx0c190YWJsZSRzaWdbKHJlc3VsdHNfdGFibGUkbm9uc2lnKV0gPC0gIm5vbnNpZyIKcmVzdWx0c190YWJsZSRzaWdbKHJlc3VsdHNfdGFibGUkREtPICYgcmVzdWx0c190YWJsZSRES09sZmM+MSldIDwtICJES08iCnJlc3VsdHNfdGFibGUkc2lnWyhyZXN1bHRzX3RhYmxlJERIWDM2ICYgcmVzdWx0c190YWJsZSRESFgzNmxmYz4xKV0gPC0gIkRIWDM2IgpyZXN1bHRzX3RhYmxlJHNpZ1socmVzdWx0c190YWJsZSRGQU5DSiAmIHJlc3VsdHNfdGFibGUkRkFOQ0psZmM+MSldIDwtICJGQU5DSiIKCndyaXRlLnRhYmxlKHJlc3VsdHNfdGFibGUsIkc0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9yZXN1bHRzLnR4dCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IFQscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQpgYGAKCmBgYHtyfQpESFgzNl9iZWQgPC0gcmVzdWx0c190YWJsZVsocmVzdWx0c190YWJsZSRESFgzNiAmIHJlc3VsdHNfdGFibGUkREhYMzZsZmM+MSksYygxLDIsMyw0LDksMTIpXQp3cml0ZS50YWJsZShESFgzNl9iZWQsIi4uL3BlYWtzL0c0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9ESFgzNl9zaWcuYmVkIiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gRixxdW90ZSA9IEYsIHNlcCA9ICJcdCIpCgpGQU5DSl9iZWQgPC0gcmVzdWx0c190YWJsZVsocmVzdWx0c190YWJsZSRGQU5DSiAmIHJlc3VsdHNfdGFibGUkRkFOQ0psZmM+MSksYygxLDIsMyw0LDEwLDEyKV0Kd3JpdGUudGFibGUoRkFOQ0pfYmVkLCIuLi9wZWFrcy9HNF9DblRfY29tYmluZWRfcGVha3NfREVTZXFfRkFOQ0pfc2lnLmJlZCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQoKREtPX2JlZCA8LSByZXN1bHRzX3RhYmxlWyhyZXN1bHRzX3RhYmxlJERLTyAmIHJlc3VsdHNfdGFibGUkREtPbGZjPjEpLGMoMSwyLDMsNCwxMSwxMildCndyaXRlLnRhYmxlKERLT19iZWQsIi4uL3BlYWtzL0c0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9ES09fc2lnLmJlZCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQoKbm9uc2lnX2JlZCA8LSByZXN1bHRzX3RhYmxlW3Jlc3VsdHNfdGFibGUkbm9uc2lnICxjKDEsMiwzLDQsMTEsMTIpXQp3cml0ZS50YWJsZShub25zaWdfYmVkLCIuLi9wZWFrcy9HNF9DblRfY29tYmluZWRfcGVha3NfREVTZXFfbm9uc2lnLmJlZCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQoKREtPX2JlZF90b3AgPC0gcmVzdWx0c190YWJsZVsocmVzdWx0c190YWJsZSRES089PVRSVUUgJiByZXN1bHRzX3RhYmxlJERLT2xmYz4yICYgcmVzdWx0c190YWJsZSRiYXNlTWVhbiA+IDEwMCksYygxLDIsMyw0LDExLDEyKV0Kd3JpdGUudGFibGUoREtPX2JlZF90b3AsIi4uL3BlYWtzL0c0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9ES09fc2lnX2xmY19iYXNlX2N1dG9mZi5iZWQiLCByb3cubmFtZXMgPSBGLCBjb2wubmFtZXMgPSBGLHF1b3RlID0gRiwgc2VwID0gIlx0IikKCgp3cml0ZS50YWJsZShjYmluZChyZXN1bHRzX3RhYmxlWyxjKDEsMiwzKV0scmVzdWx0c190YWJsZSRzaWcsYXMubnVtZXJpYyhyZXN1bHRzX3RhYmxlJHNpZyksIi4iKSwiLi4vcGVha3MvRzRfQ25UX2NvbWJpbmVkX3BlYWtzX0RFU2VxX3NpZ19jYXRlZ29yaWVzLmJlZCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IEYscXVvdGUgPSBGLCBzZXAgPSAiXHQiKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9CmxpYnJhcnkoZXVsZXJyKQp2IDwtIGxpc3QoREhYMzY9REhYMzZfYmVkJG5hbWUsRkFOQ0o9RkFOQ0pfYmVkJG5hbWUsREtPPURLT19iZWQkbmFtZSkKcGxvdF9WZW5uX2FsbCA8LSBwbG90KGV1bGVyKHYpLHF1YW50aXRpZXM9VCwgYm9yZGVyPSJibGFjayIpCnBsb3RfVmVubl9hbGwKYGBgCmBgYHtyIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9CmxpYnJhcnkoZXVsZXJyKQpES09uZWcgPC0gcmVzdWx0c190YWJsZVsocmVzdWx0c190YWJsZSRES089PVRSVUUgJiByZXN1bHRzX3RhYmxlJERLT2xmYzwgLTEpLGMoNCldCnYgPC0gbGlzdChhbGw9Y292LldUJG5hbWUsREtPbmVnPURLT25lZyxES089REtPX2JlZCRuYW1lKQpwbG90X1Zlbm5fREtPIDwtIHBsb3QoZXVsZXIodikscXVhbnRpdGllcz1UKQpwbG90X1Zlbm5fREtPCmBgYApgYGB7cn0KZGlyLmNyZWF0ZSgiLi9wbG90cyIsc2hvd1dhcm5pbmdzID0gRikKZ2dzYXZlKCJwbG90cy9wZWFrc19ERVNlcTJfTUFfREhYMzYucGRmIixwbG90X01BX0RIWDM2LHdpZHRoID0gNCwgaGVpZ2h0PSA0KQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl9NQV9GQU5DSi5wZGYiLHBsb3RfTUFfRkFOQ0osd2lkdGggPSA0LCBoZWlnaHQ9IDQpCmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX01BX0RLTy5wZGYiLHBsb3RfTUFfREtPLHdpZHRoID0gNCwgaGVpZ2h0PSA0KQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl9MRkNfREhYMzYucGRmIixwbG90X0xGQ19ES09fdnNfREhYMzYsd2lkdGggPSA0LCBoZWlnaHQ9IDQpCmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX0xGQ19GQU5DSi5wZGYiLHBsb3RfTEZDX0RLT192c19GQU5DSix3aWR0aCA9IDQsIGhlaWdodD0gNCkKZ2dzYXZlKCJwbG90cy9wZWFrc19ERVNlcTJfVmVubl9LT3MucGRmIixwbG90X1Zlbm5fYWxsLHdpZHRoID0gNCwgaGVpZ2h0PSA0KQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl9WZW5uX0RLT192c19hbGwucGRmIixwbG90X1Zlbm5fREtPLHdpZHRoID0gNCwgaGVpZ2h0PSA0KQpgYGAgCgpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00fQpsaWJyYXJ5KGNvd3Bsb3QpCmRpci5jcmVhdGUoIi4vcGFuZWxzIixzaG93V2FybmluZ3MgPSBGKQoKbGlicmFyeSgiY293cGxvdCIpCnAgPC0gZ2dkcmF3KCkgKwogIGRyYXdfcGxvdChwbG90X01BX0RIWDM2LCB4ID0gMCwgeSA9IDAuNSwgd2lkdGggPSAuMzMsIGhlaWdodCA9IC41KSArCiAgZHJhd19wbG90KHBsb3RfTUFfRkFOQ0osIHggPSAuMzMsIHkgPSAwLjUsIHdpZHRoID0gLjMzLCBoZWlnaHQgPSAuNSkgKwogIGRyYXdfcGxvdChwbG90X01BX0RLTywgeCA9IDAuNjYsIHkgPSAwLjUsIHdpZHRoID0gLjMzLCBoZWlnaHQgPSAwLjUpICsKICBkcmF3X3Bsb3QocGxvdF9MRkNfREtPX3ZzX0RIWDM2LCB4ID0gMCwgeSA9IDAsIHdpZHRoID0gMC4zMywgaGVpZ2h0ID0gMC41KSArCiAgZHJhd19wbG90KHBsb3RfTEZDX0RLT192c19GQU5DSiwgeCA9IDAuMzMsIHkgPSAwLCB3aWR0aCA9IDAuMzMsIGhlaWdodCA9IDAuNSkgKwogIGRyYXdfcGxvdChwbG90X1Zlbm5fYWxsLCB4ID0gMC42NiwgeSA9IDAsIHdpZHRoID0gMC4zMywgaGVpZ2h0ID0gMC41KSArCiAgZHJhd19wbG90X2xhYmVsKGxhYmVsID0gYygiYSIsICJiIiwgImMiLCJkIiwiZSIsImYiKSwgc2l6ZSA9IDE1LAogICAgICAgICAgICAgICAgICB4ID0gYygwLCAwLjMzLCAwLjY2LCAwLCAwLjMzLCAwLjY2KSwgeSA9IGMoMSwgMSwgMSwgMC41LCAwLjUsIDAuNSkpCnAKZ2dzYXZlKCJwYW5lbHMvcGVha3NfREVTZXEyLnBkZiIscCkKYGBgIApgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD00fQpsaWJyYXJ5KGNvd3Bsb3QpCmRpci5jcmVhdGUoIi4vcGFuZWxzIixzaG93V2FybmluZ3MgPSBGKQoKbGlicmFyeSgiY293cGxvdCIpCnAgPC0gZ2dkcmF3KCkgKwogIGRyYXdfcGxvdChwbG90X01BX0RIWDM2LCB4ID0gMCwgeSA9IDAuNSwgd2lkdGggPSAuMzMsIGhlaWdodCA9IC41KSArCiAgZHJhd19wbG90KHBsb3RfTUFfRkFOQ0osIHggPSAuMzMsIHkgPSAwLjUsIHdpZHRoID0gLjMzLCBoZWlnaHQgPSAuNSkgKwogIGRyYXdfcGxvdChwbG90X01BX0RLTywgeCA9IDAuNjYsIHkgPSAwLjUsIHdpZHRoID0gLjMzLCBoZWlnaHQgPSAwLjUpICsKICBkcmF3X3Bsb3QocGxvdF9YWV9ESFgzNiwgeCA9IDAsIHkgPSAwLCB3aWR0aCA9IDAuMzMsIGhlaWdodCA9IDAuNSkgKwogIGRyYXdfcGxvdChwbG90X1hZX0ZBTkNKLCB4ID0gMC4zMywgeSA9IDAsIHdpZHRoID0gMC4zMywgaGVpZ2h0ID0gMC41KSArCiAgZHJhd19wbG90KHBsb3RfWFlfREtPLCB4ID0gMC42NiwgeSA9IDAsIHdpZHRoID0gMC4zMywgaGVpZ2h0ID0gMC41KSArCiAgZHJhd19wbG90X2xhYmVsKGxhYmVsID0gYygiYSIsICJiIiwgImMiLCJkIiwiZSIsImYiKSwgc2l6ZSA9IDE1LAogICAgICAgICAgICAgICAgICB4ID0gYygwLCAwLjMzLCAwLjY2LCAwLCAwLjMzLCAwLjY2KSwgeSA9IGMoMSwgMSwgMSwgMC41LCAwLjUsIDAuNSkpCnAKZ2dzYXZlKCJwYW5lbHMvcGVha3NfREVTZXEyX3NjYXR0ZXIucGRmIixwKQpgYGAgCgpgYGB7cn0KY292IDwtIGNiaW5kKCBhcy5kYXRhLmZyYW1lKGNvdi5XVClbLDE6OF0sIAogICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUoY292LkRIWDM2KVssNjo4XSwgCiAgICAgICAgICAgICAgYXMuZGF0YS5mcmFtZShjb3YuRkFOQ0opWyw2OjhdLCAKICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKGNvdi5ES08pWyw2OjhdKQoKY29sbmFtZXMoY292KSA8LSBjKGNvbG5hbWVzKGNvdilbMTo1XSwiV1QxIiwiV1QyIiwiV1QzIiwiREhYMSIsIkRIWDIiLCJESFgzIiwiRkFOMSIsIkZBTjIiLCJGQU4zIiwiREtPMSIsIkRLTzIiLCJES08zIikKCnJvd25hbWVzKGNvdikgPC0gYXMuZGF0YS5mcmFtZShjb3YuV1QpJG5hbWUKCmNvdiRESFgzNl9zaWcgPC0gcm93bmFtZXMoY292KSAlaW4lIERIWDM2X2JlZCRuYW1lCmNvdiRGQU5DSl9zaWcgPC0gcm93bmFtZXMoY292KSAlaW4lIEZBTkNKX2JlZCRuYW1lCmNvdiRES09fc2lnIDwtIHJvd25hbWVzKGNvdikgJWluJSBES09fYmVkJG5hbWUKY292JG5vbl9zaWcgPC0gd2l0aChjb3YsICEoREhYMzZfc2lnIHwgRkFOQ0pfc2lnIHwgREtPX3NpZykpCmBgYAoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9M30KbGlicmFyeShyZXNoYXBlMikKbWRmIDwtIG1lbHQoZGF0YS5mcmFtZShuYW1lPXJvd25hbWVzKGNvdiksY292Wyw2OjIxXSkpCm1kZiA8LSBtZGZbbWRmJHZhbHVlPDUwMCxdCm1kZiRjb25kIDwtICJXVCIKbWRmJGNvbmRbZ3JlcCgiREhYIixtZGYkdmFyaWFibGUpXSA8LSAiREhYMzYtLy0iCm1kZiRjb25kW2dyZXAoIkZBTiIsbWRmJHZhcmlhYmxlKV0gPC0gIkZBTkNKLS8tIgptZGYkY29uZFtncmVwKCJES08iLG1kZiR2YXJpYWJsZSldIDwtICJESFgzNi0vLUZBTkNKLS8tIgpwbG90X3Zpb2xfcmVwX2FsbF9wZWFrcyA8LSBnZ3Zpb2xpbihtZGYsIHg9InZhcmlhYmxlIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDUwKSkKcGxvdF92aW9sX3JlcF9hbGxfcGVha3MKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0zfQpwbG90X3Zpb2xfcmVwX0RIWDM2X3BlYWtzIDwtIGdndmlvbGluKG1kZlttZGYkREhYMzZfc2lnLF0sIHg9InZhcmlhYmxlIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDUwKSkKcGxvdF92aW9sX3JlcF9ESFgzNl9wZWFrcwpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTN9CmdndmlvbGluKG1kZlttZGYkRkFOQ0pfc2lnLF0sIHg9InZhcmlhYmxlIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDUwKSkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0zfQpwbG90X3Zpb2xfcmVwX0RLT19wZWFrcyA8LSBnZ3Zpb2xpbihtZGZbbWRmJERLT19zaWcsXSwgeD0idmFyaWFibGUiLHk9InZhbHVlIixmaWxsPSJjb25kIixwYWxldHRlID0gbXlwYWwsIGFkZD0ibWVhbl9zZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsNTApKQpwbG90X3Zpb2xfcmVwX0RLT19wZWFrcwpgYGAKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9M30KcGxvdF92aW9sX3JlcF9ub25zaWdfcGVha3MgPC0gZ2d2aW9saW4obWRmW21kZiRub25fc2lnLF0sIHg9InZhcmlhYmxlIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDUwKSkKcGxvdF92aW9sX3JlcF9ub25zaWdfcGVha3MKYGBgCgpgYGB7cn0KZ2dzYXZlKCJwbG90cy9wZWFrc19ERVNlcTJfdmlvbF9yZXBfYWxsLnBkZiIscGxvdF92aW9sX3JlcF9hbGxfcGVha3MpCmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX3Zpb2xfcmVwX0RLTy5wZGYiLHBsb3RfdmlvbF9yZXBfREtPX3BlYWtzKQpnZ3NhdmUoInBsb3RzL3BlYWtzX0RFU2VxMl92aW9sX3JlcF9ESFgzNi5wZGYiLHBsb3RfdmlvbF9yZXBfREhYMzZfcGVha3MpCmdnc2F2ZSgicGxvdHMvcGVha3NfREVTZXEyX3Zpb2xfcmVwX25vbnNpZy5wZGYiLHBsb3RfdmlvbF9yZXBfbm9uc2lnX3BlYWtzKQpgYGAgCgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0zfQpzZGYgPC0gYWdncmVnYXRlKHZhbHVlIH4gbmFtZSArIGNvbmQsIGRhdGE9bWRmLCBGVU49Im1lYW4iKQpzZGYkY29uZCA8LSBmYWN0b3Ioc2RmJGNvbmQsbGV2ZWxzPWMoIldUIiwiREhYMzYtLy0iLCJGQU5DSi0vLSIsIkRIWDM2LS8tRkFOQ0otLy0iKSkKZ2d2aW9saW4oc2RmLCB4PSJjb25kIix5PSJ2YWx1ZSIsZmlsbD0iY29uZCIscGFsZXR0ZSA9IG15cGFsW2MoNCwxLDIsMyldLCBhZGQ9Im1lYW5fc2QiKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDUwKSkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0zfQpzZGYkREhYMzZfc2lnIDwtIHNkZiRuYW1lICVpbiUgREhYMzZfYmVkJG5hbWUKc2RmJEZBTkNKX3NpZyA8LSBzZGYkbmFtZSAlaW4lIEZBTkNKX2JlZCRuYW1lCnNkZiRES09fc2lnIDwtIHNkZiRuYW1lICVpbiUgREtPX2JlZCRuYW1lCnNkZiRES09fdG9wIDwtIHNkZiRuYW1lICVpbiUgREtPX2JlZF90b3AkbmFtZQpnZ3Zpb2xpbihzZGZbc2RmJERIWDM2LF0sIHg9ImNvbmQiLHk9InZhbHVlIixmaWxsPSJjb25kIixwYWxldHRlID0gbXlwYWxbYyg0LDEsMiwzKV0sIGFkZD0ibWVhbl9zZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsNzUpKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTN9CmdndmlvbGluKHNkZltzZGYkRkFOQ0pfc2lnLF0sIHg9ImNvbmQiLHk9InZhbHVlIixmaWxsPSJjb25kIixwYWxldHRlID0gbXlwYWxbYyg0LDEsMiwzKV0sIGFkZD0ibWVhbl9zZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsNzUpKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTN9CnBsb3RfdmlvbF9ES09fcGVha3MgPC0gZ2d2aW9saW4oc2RmW3NkZiRES09fc2lnLF0sIHg9ImNvbmQiLHk9InZhbHVlIixmaWxsPSJjb25kIixwYWxldHRlID0gbXlwYWxbYyg0LDEsMiwzKV0sIGFkZD0ibWVhbl9zZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsNzUpKQpwbG90X3Zpb2xfREtPX3BlYWtzCmBgYAoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9M30KZ2d2aW9saW4oc2RmW3NkZiRES09fdG9wLF0sIHg9ImNvbmQiLHk9InZhbHVlIixmaWxsPSJjb25kIixwYWxldHRlID0gbXlwYWxbYyg0LDEsMiwzKV0sIGFkZD0ibWVhbl9zZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDAsNzUpKQpgYGAKCiMjIyBhbm5vdGF0ZSBwZWFrIHRhYmxlCmBgYHtyfQpsaWJyYXJ5KGJlZHNjb3V0KQoKYmVkX3BlYWtzIDwtIHJ0cmFja2xheWVyOjppbXBvcnQocGVha191bml2ZXJzZSkKY2hyb21obW1fZ3IgPC0gcnRyYWNrbGF5ZXI6OmltcG9ydChjaHJvbWhtbSkKCgpiZWRfcGVha3NfYW5ub3RhdGVkIDwtIGltcHV0ZV9mZWF0dXJlKGJlZF9wZWFrcywgY2hyb21obW1fZ3IsICJuYW1lIikKYmVkX3BlYWtzX2Fubm90YXRlZF9kZiA8LSBhcy5kYXRhLmZyYW1lKHVuaXF1ZShiZWRfcGVha3NfYW5ub3RhdGVkKSkKIyBJZiB5b3Ugd2FudCB0byBleHBvcnQgdG8gQkVEIGZpbGUgd2l0aCBydHJhY2tsYXllciB0aGVuIHlvdQojIGRvIG5lZWQgdG8gZXhwbGljaXRseSBvdmVyd3JpdGUgdGhlIG5hbWU6CmJlZF9wZWFrc19hbm5vdGF0ZWQkbmFtZSA8LSBiZWRfcGVha3NfYW5ub3RhdGVkJGZlYXR1cmUKcnRyYWNrbGF5ZXI6OmV4cG9ydCh1bmlxdWUoYmVkX3BlYWtzX2Fubm90YXRlZCksICIuLi9wZWFrcy9HNF9DblRfY29tYmluZWRfcGVha3NfREVTZXFfYW5ub3RhdGVkX3YyLmJlZCIpCgpjaHJvbWhtbTE3X2dyIDwtIHJ0cmFja2xheWVyOjppbXBvcnQoIi4uL2dlbm9tZS9DaHJvbUhNTTE3LmNocjkubW0zOWxpZnQuYmVkIikKYmVkX3BlYWtzX2htbTE3IDwtIGltcHV0ZV9mZWF0dXJlKGJlZF9wZWFrcywgY2hyb21obW0xN19nciwgIm5hbWUiKQojIElmIHlvdSB3YW50IHRvIGV4cG9ydCB0byBCRUQgZmlsZSB3aXRoIHJ0cmFja2xheWVyIHRoZW4geW91CiMgZG8gbmVlZCB0byBleHBsaWNpdGx5IG92ZXJ3cml0ZSB0aGUgbmFtZToKYmVkX3BlYWtzX2htbTE3JG5hbWUgPC0gYmVkX3BlYWtzX2htbTE3JGZlYXR1cmUKYmVkX3BlYWtzX2htbTE3JHNjb3JlW2lzLm5hKGJlZF9wZWFrc19obW0xNyRzY29yZSldIDwtIDAKcnRyYWNrbGF5ZXI6OmV4cG9ydCh1bmlxdWUoYmVkX3BlYWtzX2htbTE3KSwgIi4uL3BlYWtzL0c0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9hbm5vdGF0ZWRfQ2hyb21ITU0xNy5iZWQiKQoKcm1za19nciA8LSBydHJhY2tsYXllcjo6aW1wb3J0KCIuLi9nZW5vbWUvcm1zay5sdDIwMGJwLm1tMzkuYmVkIikKYmVkX3BlYWtzX3Jtc2sgPC0gaW1wdXRlX2ZlYXR1cmUoYmVkX3BlYWtzLCBybXNrX2dyLCAibmFtZSIpCiMgSWYgeW91IHdhbnQgdG8gZXhwb3J0IHRvIEJFRCBmaWxlIHdpdGggcnRyYWNrbGF5ZXIgdGhlbiB5b3UKIyBkbyBuZWVkIHRvIGV4cGxpY2l0bHkgb3ZlcndyaXRlIHRoZSBuYW1lOgpiZWRfcGVha3Nfcm1zayRuYW1lIDwtIGJlZF9wZWFrc19ybXNrJGZlYXR1cmUKYmVkX3BlYWtzX3Jtc2skc2NvcmVbaXMubmEoYmVkX3BlYWtzX3Jtc2skc2NvcmUpXSA8LSAwCnJ0cmFja2xheWVyOjpleHBvcnQoYmVkX3BlYWtzX3Jtc2ssICIuLi9wZWFrcy9HNF9DblRfY29tYmluZWRfcGVha3NfREVTZXFfYW5ub3RhdGVkX3Jtc2suYmVkIikKCmJlZF9wZWFrc190YWJsZSA8LSBjYmluZChiZWRfcGVha3NfYW5ub3RhdGVkX2RmLGRhdGEuZnJhbWUoYmFzZU1lYW49bGZjX0RLTyRiYXNlTWVhbixESFgzNj0oZGF0YV9ESFgzNiRpc0RFICYgZGF0YV9ESFgzNiRsZmM+MSksRkFOQ0o9KGRhdGFfRkFOQ0okaXNERSAmIGRhdGFfRkFOQ0okbGZjPjEpLERLTz0oZGF0YV9ES08kaXNERSZkYXRhX0RLTyRsZmM+MSksREhYMzZsZmM9ZGF0YV9ESFgzNiRsZmMsRkFOQ0psZmM9ZGF0YV9GQU5DSiRsZmMsREtPbGZjPWRhdGFfREtPJGxmYykpCgp3cml0ZS50YWJsZShiZWRfcGVha3NfdGFibGUsIkc0X0NuVF9jb21iaW5lZF9wZWFrc19ERVNlcV9hbm5vdGF0ZWRfdjIudHh0Iiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gVCxxdW90ZSA9IEYsIHNlcCA9ICJcdCIpCmBgYAoKYGBge3IgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9Mn0KI3JlYWQgaW4gLSBpZiB5b3Ugd2FudCB0byBza2lwIGRlIG5vdm8gZ2VuZXJhdGlvbgpiZWRfcGVha3NfdGFibGUgPC0gcmVhZC50YWJsZSgiRzRfQ25UX2NvbWJpbmVkX3BlYWtzX0RFU2VxX2Fubm90YXRlZF92Mi50eHQiLCBoZWFkZXIgPSBULCBzZXAgPSAiXHQiKQoKdnBhbD1jb2xvclJhbXBQYWxldHRlKGMoImNvcm5mbG93ZXJibHVlIiwib3JhbmdlIiwicmVkMiIpKQpzdGF0cyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKGJlZF9wZWFrc190YWJsZSRmZWF0dXJlKSkKZ2dkb251dGNoYXJ0KHN0YXRzLHggPSAiRnJlcSIsbGFiZWw9IlZhcjEiLGZpbGw9dnBhbCgxMCkpCmBgYAoKIyMjIERKIFBlYWsgQW5ub3RhdGlvbgpgYGB7ciBmaWcuaGVpZ2h0PTIsIGZpZy53aWR0aD0yfQpzdGF0cyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKGJlZF9wZWFrc190YWJsZSRmZWF0dXJlW2JlZF9wZWFrc190YWJsZSRES09dKSkKcGxvdF9kb251dF9ESiA8LSBnZ2RvbnV0Y2hhcnQoc3RhdHMseCA9ICJGcmVxIixsYWJlbD0iVmFyMSIsZmlsbD12cGFsKDEwKSkKcGxvdF9kb251dF9ESgpgYGAKCiMjIyBub24tREogUGVhayBBbm5vdGF0aW9uCmBgYHtyIGZpZy5oZWlnaHQ9MiwgZmlnLndpZHRoPTJ9CnN0YXRzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoYmVkX3BlYWtzX3RhYmxlJGZlYXR1cmVbIWJlZF9wZWFrc190YWJsZSRES08gJiAhYmVkX3BlYWtzX3RhYmxlJERIWDM2ICYgIWJlZF9wZWFrc190YWJsZSRGQU5DSl0pKQpwbG90X2RvbnV0X25vbkRKIDwtIGdnZG9udXRjaGFydChzdGF0cyx4ID0gIkZyZXEiLGxhYmVsPSJWYXIxIixmaWxsPXZwYWwoMTApKQpwbG90X2RvbnV0X25vbkRKCmBgYAoKYGBge3IgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9NH0KdnBhbD1jb2xvclJhbXBQYWxldHRlKGMoImxpZ2h0Z3JlZW4iLCJjb3JuZmxvd2VyYmx1ZSIsIm9yYW5nZSIsInJlZDIiKSkKCnN0YXRzIDwtIGRhdGEuZnJhbWUoYXMuZGF0YS5mcmFtZSh0YWJsZShiZWRfcGVha3NfdGFibGUkZmVhdHVyZSkpWzFdLGFzLmRhdGEuZnJhbWUodGFibGUoYmVkX3BlYWtzX3RhYmxlJGZlYXR1cmVbYmVkX3BlYWtzX3RhYmxlJERLT10pKVsyXSxhcy5kYXRhLmZyYW1lKHRhYmxlKGJlZF9wZWFrc190YWJsZSRmZWF0dXJlWyFiZWRfcGVha3NfdGFibGUkREtPICYgIWJlZF9wZWFrc190YWJsZSRESFgzNiAmICFiZWRfcGVha3NfdGFibGUkRkFOQ0pdKSlbMl0pCgpjb2xuYW1lcyhzdGF0cykgPC0gYygiU3RhdGUiLCJESiIsIm5vbkRKIikKCiNzdGF0cyRESFgzNj1zdGF0cyRESi9zdW0oc3RhdHMkREopKjEwMAojc3RhdHMkRkFOQ0o9c3RhdHMkbm9uREovc3VtKHN0YXRzJG5vbkRKKSoxMDAKCm1kZiA8LSBtZWx0KHN0YXRzKQptZGYkU3RhdGUgPC0gZmFjdG9yKG1kZiRTdGF0ZSxsZXZlbHM9bGV2ZWxzKG1kZiRTdGF0ZSlbYygxLDMsNSw3LDQsNiwxMCw4LDksMildKQpjb2xzPWModnBhbCgxMSlbYyg0LDUsMywyLDksOCw3KV0sIiNEREREREQiLCIjRUVFRUVFIix2cGFsKDExKVsxMF0pCnBsb3RfYmFyX2Nocm9taG1tX2Fubm8gPC0gZ2diYXJwbG90KG1kZix4ID0gInZhcmlhYmxlIix5PSJ2YWx1ZSIsZmlsbD0iU3RhdGUiLHBhbGV0dGUgPWNvbHMsICBvcmllbnRhdGlvbiA9IGMoImhvcml6b250YWwiKSkgCnBsb3RfYmFyX2Nocm9taG1tX2Fubm8KYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD00fQpzdGF0cyRESj1zdGF0cyRESi9zdW0oc3RhdHMkREopKjEwMApzdGF0cyRub25ESj1zdGF0cyRub25ESi9zdW0oc3RhdHMkbm9uREopKjEwMAoKbWRmIDwtIG1lbHQoc3RhdHMpCm1kZiRTdGF0ZSA8LSBmYWN0b3IobWRmJFN0YXRlLGxldmVscz1sZXZlbHMobWRmJFN0YXRlKVtjKDEsMyw1LDcsNCw2LDEwLDgsOSwyKV0pCmNvbHM9Yyh2cGFsKDExKVtjKDQsNSwzLDIsOSw4LDcpXSwiI0RERERERCIsIiNFRUVFRUUiLHZwYWwoMTEpWzEwXSkKcGxvdF9iYXJfY2hyb21obW1fYW5ub19ub3JtIDwtIGdnYmFycGxvdChtZGYseCA9ICJ2YXJpYWJsZSIseT0idmFsdWUiLGZpbGw9IlN0YXRlIixwYWxldHRlID1jb2xzLCAgb3JpZW50YXRpb24gPSBjKCJob3Jpem9udGFsIikpIApwbG90X2Jhcl9jaHJvbWhtbV9hbm5vX25vcm0KYGBgCmBgYHtyfQpnZ3NhdmUoInBsb3RzL3Bsb3RfYmFyX2Nocm9taG1tLnBkZiIscGxvdF9iYXJfY2hyb21obW1fYW5ubykKZ2dzYXZlKCJwbG90cy9wbG90X2Jhcl9jaHJvbWhtbV9yZWwucGRmIixwbG90X2Jhcl9jaHJvbWhtbV9hbm5vX25vcm0pCmBgYCAKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTN9CnZwYWw9Y29sb3JSYW1wUGFsZXR0ZShjKCJsaWdodGdyZWVuIiwiY29ybmZsb3dlcmJsdWUiLCJvcmFuZ2UiLCJyZWQyIikpCgpzdGF0cyA8LSBkYXRhLmZyYW1lKGFzLmRhdGEuZnJhbWUodGFibGUoYmVkX3BlYWtzX3RhYmxlJGZlYXR1cmUpKSxESFgzNj1hcy5kYXRhLmZyYW1lKHRhYmxlKGJlZF9wZWFrc190YWJsZSRmZWF0dXJlW2JlZF9wZWFrc190YWJsZSRESFgzNj09VFJVRV0pKVsyXSxGQU5DSj1hcy5kYXRhLmZyYW1lKHRhYmxlKGJlZF9wZWFrc190YWJsZSRmZWF0dXJlW2JlZF9wZWFrc190YWJsZSRGQU5DSj09VFJVRV0pKVsyXSxES089YXMuZGF0YS5mcmFtZSh0YWJsZShiZWRfcGVha3NfdGFibGUkZmVhdHVyZVtiZWRfcGVha3NfdGFibGUkREtPPT1UUlVFXSkpWzJdKQpjb2xuYW1lcyhzdGF0cykgPC0gYygiU3RhdGUiLCJUb3RhbCIsIkRIWDM2IiwiRkFOQ0oiLCJES08iKQoKc3RhdHMkVG90YWw9c3RhdHMkVG90YWwvc3VtKHN0YXRzJFRvdGFsKSoxMDAKc3RhdHMkREhYMzY9c3RhdHMkREhYMzYvc3VtKHN0YXRzJERIWDM2KSoxMDAKc3RhdHMkRkFOQ0o9c3RhdHMkRkFOQ0ovc3VtKHN0YXRzJEZBTkNKKSoxMDAKc3RhdHMkREtPPXN0YXRzJERLTy9zdW0oc3RhdHMkREtPKSoxMDAKbWRmIDwtIG1lbHQoc3RhdHMpCm1kZiRTdGF0ZSA8LSBmYWN0b3IobWRmJFN0YXRlLGxldmVscz1sZXZlbHMobWRmJFN0YXRlKVtjKDEsMyw1LDcsNCw2LDEwLDgsOSwyKV0pCmNvbHM9Yyh2cGFsKDExKVtjKDQsNSwzLDIsOSw4LDcpXSwiI0RERERERCIsIiNFRUVFRUUiLHZwYWwoMTEpWzEwXSkKcGxvdF9iYXJfY2hyb21obW1fYW5ubyA8LSBnZ2JhcnBsb3QobWRmLHggPSAidmFyaWFibGUiLHk9InZhbHVlIixmaWxsPSJTdGF0ZSIscGFsZXR0ZSA9Y29scyxsYWJlbD1tZGYkU3RhdGUpCnBsb3RfYmFyX2Nocm9taG1tX2Fubm8KYGBgCgoKCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTN9CnAgPC0gZ2dkcmF3KCkgKwogIGRyYXdfcGxvdChwbG90X2Jhcl9jaHJvbWhtbV9hbm5vLCB4ID0gMCwgeSA9IDAsIHdpZHRoID0gLjIwLCBoZWlnaHQgPSAxKSArCiAgZHJhd19wbG90KHBsb3RfdmlvbF9yZXBfREtPX3BlYWtzLCB4ID0gLjIsIHkgPSAwLCB3aWR0aCA9IC40MCwgaGVpZ2h0ID0gMC43KSArCiAgZHJhd19wbG90KHBsb3RfdmlvbF9yZXBfbm9uc2lnX3BlYWtzLCB4ID0gMC42LCB5ID0gMCwgd2lkdGggPSAuNDAsIGhlaWdodCA9IDAuNykgKwogIGRyYXdfcGxvdF9sYWJlbChsYWJlbCA9IGMoImEiLCAiYiIsICJjIiksIHNpemUgPSAxNSwKICAgICAgICAgICAgICAgICAgeCA9IGMoMCwgMC4yLCAwLjYpLCB5ID0gYygxLCAwLjgsIDAuOCkpCnAKZ2dzYXZlKCJwYW5lbHMvcGVha19hbm5vX3Zpb2xpbl92MS5wZGYiLHApCmBgYCAKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9M30KCnAgPC0gZ2dkcmF3KCkgKwogIGRyYXdfcGxvdChwbG90X2Jhcl9jaHJvbWhtbV9hbm5vLCB4ID0gMCwgeSA9IDAsIHdpZHRoID0gLjQsIGhlaWdodCA9IDEpICsKICBkcmF3X3Bsb3QocGxvdF92aW9sX3JlcF9ES09fcGVha3MsIHggPSAuNCwgeSA9IDAuNSwgd2lkdGggPSAuNjAsIGhlaWdodCA9IDAuNSkgKwogIGRyYXdfcGxvdChwbG90X3Zpb2xfcmVwX25vbnNpZ19wZWFrcywgeCA9IDAuNCwgeSA9IDAsIHdpZHRoID0gLjYwLCBoZWlnaHQgPSAwLjUpICsKICBkcmF3X3Bsb3RfbGFiZWwobGFiZWwgPSBjKCJhIiwgImIiLCAiYyIpLCBzaXplID0gMTUsCiAgICAgICAgICAgICAgICAgIHggPSBjKDAsIDAuNCwgMC40KSwgeSA9IGMoMSwgMSwgMC41KSkKcApnZ3NhdmUoInBhbmVscy9wZWFrX2Fubm9fdmlvbGluX3YyLnBkZiIscCkKYGBgIAo=